package dd.lo.practice;

import dd.lo.util.ImageUtils;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.apache.commons.lang3.math.NumberUtils;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.Rect;
import org.opencv.imgcodecs.Imgcodecs;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

public class PutChineseDisplay extends Application {

    public static void start(String[] args) {
        launch(args);
    }

    private static final int DEFAULT_WIDTH = 1200;
    private static final int DEFAULT_HEIGHT = 900;

    private Mat srcImg;

    private SimpleStringProperty text; //要写入到图片上的中文

    private ImageView imageView;

    private void imageProcess() {
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() {
                if (null == srcImg || srcImg.empty()) return null;
                Mat midImg = new Mat();
                srcImg.copyTo(midImg);
                //将图片转成BufferedImage以方便后续操作
                int imgType = midImg.channels() > 1 ? BufferedImage.TYPE_3BYTE_BGR : BufferedImage.TYPE_BYTE_GRAY;
                BufferedImage bi = null;
                bi = new BufferedImage(midImg.cols(), midImg.rows(), imgType);
                for (int y = 0; y < midImg.rows(); ++y) {
                    for (int x = 0; x < midImg.cols(); ++x) {
                        int rgb;
                        double[] pixel = midImg.get(y, x);
                        if (BufferedImage.TYPE_3BYTE_BGR == imgType) {
                            rgb = ((int) pixel[2] << 16) | ((int) pixel[1] << 8) | ((int) pixel[0]); //Mat里面是BGR，所以要调转过来
                        } else {
                            rgb = (int) pixel[0];
                        }
                        bi.setRGB(x, y, rgb);
                    }
                }
                Graphics2D g = bi.createGraphics(); //创建一个Graphics2D用于进行绘图
                Font f = new Font("SimSun", Font.PLAIN, 56);
                g.setFont(f);
                g.setColor(new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255)));
                int x = midImg.cols() / 4 + (int) (Math.random() * (midImg.cols() / 2)), y = midImg.rows() / 4 + (int) (Math.random() * (midImg.rows() / 2));
                g.drawString(text.get(), x, y);
                g.dispose();
                //将BufferedImage利用ImageIO.write按jpeg格式输出到ByteArrayOutputStream流中
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                try {
                    ImageIO.write(bi, "jpeg", byteArrayOutputStream);
                    byteArrayOutputStream.flush();
                } catch (IOException e) {
                    return null;
                }
                //此时就可以得到图片的byte信息，在ByteArrayOutputStream中，然后就可以通过byte信息将图片load到Mat中
                Mat viewImg = Imgcodecs.imdecode(new MatOfByte(byteArrayOutputStream.toByteArray()), Imgcodecs.IMREAD_UNCHANGED);
                ImageUtils.fitImgSize(viewImg, viewImg, DEFAULT_WIDTH, DEFAULT_HEIGHT);
                MatOfByte buffer = new MatOfByte();
                Imgcodecs.imencode(".jpeg", viewImg, buffer);
                Platform.runLater(() -> {
                    imageView.setImage(new Image(new ByteArrayInputStream(buffer.toArray())));
                });
                return null;
            }
        };
        new Thread(task).start();
    }

    @Override
    public void start(Stage stage) throws Exception {
        Button imgChooserBtn = new Button("选择图片");
        imgChooserBtn.setOnMouseClicked(e -> {
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("选择图片");
            fileChooser.setInitialDirectory(new File(System.getProperty("user.home") + "/Downloads")
            );
            fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("All Images", "*.*"));
            File imgFile = fileChooser.showOpenDialog(stage);
            if (null == imgFile) return;
            srcImg = Imgcodecs.imread(imgFile.getAbsolutePath(), Imgcodecs.IMREAD_UNCHANGED);
            if (srcImg.empty()) System.out.println("图片读取失败");
            imageProcess();
        });
        //文本输入框
        text = new SimpleStringProperty();
        TextField inputText = new TextField();
        text.bind(inputText.textProperty());
        Button drawBtn = new Button("绘制");
        drawBtn.setOnMouseClicked(e -> imageProcess());
        //关闭按钮
        Button exitBtn = new Button("关闭");
        exitBtn.setOnMouseClicked(e -> Platform.exit());
        VBox rows = new VBox(0);
        rows.setPadding(new Insets(10, 10, 0, 10));
        HBox row0 = new HBox(10);
        row0.setPadding(new Insets(5, 0, 5, 0));
        row0.getChildren().addAll(imgChooserBtn, new Text("请输入字符："), inputText, drawBtn, exitBtn);
        rows.getChildren().addAll(row0);
        imageView = new ImageView();
        BorderPane root = new BorderPane();
        root.setCenter(imageView);
        root.setBottom(rows);
        Scene scene = new Scene(root, DEFAULT_WIDTH, DEFAULT_HEIGHT + 50);
        stage.setScene(scene);
        stage.setTitle("向图片中添加中文字演示");
        stage.setResizable(false);
        stage.show();
    }
}
